package com.cq.hd.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.regex.Pattern;


@Slf4j
public class FileUtils {

    private final static String pattern = Pattern.compile("\\\\").pattern();

    public static boolean isContain(String extensions, String fileName) {
        try {
            String[] extensionArray = extensions.split(",");
            String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
            fileExtension = fileExtension.toLowerCase();
            for (String extension : extensionArray) {
                if (extension.trim().equals(fileExtension)) {
                    return false;
                }
            }
        } catch (Exception e) {
            log.error("上传图片异常", e);
        }
        return true;
    }

    public static File save(byte[] bytes, String fullPath, String serverPath) {
        if (StringUtils.isEmpty(fullPath)) {
            throw new RuntimeException("文件路劲不能为空");
        }
        long begin = System.currentTimeMillis();
        fullPath = fullPath.replaceAll(pattern, "/").replaceAll("//{1,}", "/");
        int lastSeparator = fullPath.lastIndexOf("/");
        String path = fullPath.substring(0, lastSeparator);
        log.debug("本地存储save-path:{}", path);
        String fileName = fullPath.substring(lastSeparator + 1);
        try {
            File destFile = createDestFile(path, fileName, serverPath);
            checkFile(destFile);
            org.apache.commons.io.FileUtils.writeByteArrayToFile(destFile, bytes);

            return destFile;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            log.debug("完成从本地存储获取文件: {}", System.currentTimeMillis() - begin);
        }

        return null;
    }


    /**
     * 校验文件是否存在, 并给出异常信息
     *
     * @param file 需要校验的文件
     * @Author 滕鑫源
     * @Date 2020/8/26 11:57
     **/
    private static void checkFile(File file) {
        if (file.exists()) {
            log.warn("指定的文件已存在, 本次操作将会覆盖: {}", file.getAbsolutePath());
            if (file.isDirectory()) {
                log.error("指定的文件是文件夹, 保存文件操作无法进行.");
                throw new RuntimeException("指定的文件是文件夹, 保存文件操作无法进行.");
            }
        }
    }

    /**
     * 根据存储地址, 根路径和文件名, 创建本地文件
     *
     * @param path
     * @param fileName
     * @return
     */
    private static File createDestFile(String path, String fileName, String serverPath) {
        log.debug("开始向本地存储保存文件: {}", serverPath);
        File rootDir = new File(serverPath);
        if (path == null) {
            path = "";
        }
        File destDir = new File(rootDir, path);
        log.debug("本地存储绝对路劲: {}", destDir.getAbsolutePath());
        createDirectory(destDir.getAbsolutePath());
        return new File(destDir, fileName);
    }

    /**
     * 创建目录
     *
     * @param descDirName 目录名,包含路径
     * @return 如果创建成功，则返回true，否则返回false
     */
    public static boolean createDirectory(String descDirName) {
        String descDirNames = descDirName;
        if (!descDirNames.endsWith(File.separator)) {
            descDirNames = descDirNames + File.separator;
        }
        File descDir = new File(descDirNames);
        if (descDir.exists()) {
            log.debug("目录 " + descDirNames + " 已存在!");
            return false;
        }
        // 创建目录
        if (descDir.mkdirs()) {
            log.debug("目录 " + descDirNames + " 创建成功!");
            return true;
        } else {
            log.debug("目录 " + descDirNames + " 创建失败!");
            return false;
        }

    }

    public static String getUri(String url, HttpServletRequest request) {
        if (StringUtils.isEmpty(url)) {
            return "";
        } else if (url.startsWith("http://") || url.startsWith("https://")) {
            return url;
        }
        return request.getScheme() + "://" + request.getServerName() + url;
    }

    /**
     * 删除文件，可以删除单个文件或文件夹
     *
     * @param fileName 被删除的文件名
     * @return 如果删除成功，则返回true，否是返回false
     */
    public static boolean delFile(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            log.debug(fileName + " 文件不存在!");
            return true;
        } else {
            if (file.isFile()) {
                return FileUtils.deleteFile(fileName);
            } else {
                return FileUtils.deleteDirectory(fileName);
            }
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName 被删除的文件名
     * @return 如果删除成功，则返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                log.debug("删除文件 " + fileName + " 成功!");
                return true;
            } else {
                log.debug("删除文件 " + fileName + " 失败!");
                return false;
            }
        } else {
            log.debug(fileName + " 文件不存在!");
            return true;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param dirName 被删除的目录所在的文件路径
     * @return 如果目录删除成功，则返回true，否则返回false
     */
    public static boolean deleteDirectory(String dirName) {
        String dirNames = dirName;
        if (!dirNames.endsWith(File.separator)) {
            dirNames = dirNames + File.separator;
        }
        File dirFile = new File(dirNames);
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            log.debug(dirNames + " 目录不存在!");
            return true;
        }
        boolean flag = true;
        // 列出全部文件及子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = FileUtils.deleteFile(files[i].getAbsolutePath());
                // 如果删除文件失败，则退出循环
                if (!flag) {
                    break;
                }
            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                flag = FileUtils.deleteDirectory(files[i]
                        .getAbsolutePath());
                // 如果删除子目录失败，则退出循环
                if (!flag) {
                    break;
                }
            }
        }

        if (!flag) {
            log.debug("删除目录失败!");
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            log.debug("删除目录 " + dirName + " 成功!");
            return true;
        } else {
            log.debug("删除目录 " + dirName + " 失败!");
            return false;
        }
    }

    public static MultipartFile createMultipartFile(InputStream inputStream, String fileName) throws IOException {
        return new MockMultipartFile(
                fileName,
                fileName,
                ContentType.APPLICATION_OCTET_STREAM.toString(),
                inputStream
        );
    }

}
